package com.hds.hcp.apihelpers.query.result;

import java.io.IOException;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;

/**
 * This class represents the <code>facets</code> part of the <code>queryResult</code>
 * that is returned by an HCP object query request. 
 * <p> 
 * The class is constructed as a Bean to facilitate utilizing Jackson JSON 
 * serializer to create JSON formatted requests. The Jackson JSON component
 * will interpret the Bean format and populate this object when parsing the
 * stream.
 * 
 * @version 5.0
 */
public class Facets {
	private enum ParseLevel { BEGIN_FACETS, ARRAY_ELEMENT, END_FACETS };
	private Boolean isLast = false;
	private Boolean isInitialized = false;
	private JsonParser jp = null;
	private ParseLevel parseContext = ParseLevel.BEGIN_FACETS;
	private FacetRecord previousRecord = null, currentRecord = null;
	private Integer recordCount = 0;
	
	public Facets() {};
	
	public Facets(JsonParser inJsonParser) { setParser(inJsonParser); };
	
	public void setParser(JsonParser inJsonParser)
	{
		jp = inJsonParser; 
		parseContext = ParseLevel.BEGIN_FACETS;
		isLast=false;
		isInitialized=true;
		recordCount = 0;
	};

	public Boolean isInitialized() { return isInitialized; };
	
	public Integer getRecordsRead() { return recordCount; };
	
	public FacetRecord getPriorRecord() { return previousRecord; };
	
	public FacetRecord getNext() throws JsonParseException, IOException {
		return getNext(false);
	}
	public FacetRecord getNext(Boolean inDebug) throws JsonParseException, IOException {
		JsonToken token;
		
		if ( ! isInitialized )
			throw new JsonParseException("Facets object is not properly initialized", null);
		
		// If we are starting from the beginning, make sure we are at the right context.
		if (parseContext == ParseLevel.BEGIN_FACETS)
		{
			if (inDebug)
				System.out.println("Token: " + jp.getCurrentToken() + " Name: " + jp.getCurrentName());
			
			// Make sure we are at the start of the resultSet field.
			if (! (JsonToken.FIELD_NAME == jp.getCurrentToken() && "facets".equals(jp.getCurrentName())))
				throw new JsonParseException("Invalid Context trying to parse facets", null);
			
			// Make sure we have an Array to process.
			if (jp.nextToken() != JsonToken.START_ARRAY)
				throw new JsonParseException("Invalid form. facets is not an ARRAY", null);
			
			parseContext = ParseLevel.ARRAY_ELEMENT;
			
			jp.nextToken();  // Move to next token for array elements.
		}

		if (parseContext != ParseLevel.ARRAY_ELEMENT)
			throw new JsonParseException("Invalid internal state in Facets", null);
		
		previousRecord = currentRecord;
		currentRecord = null;

		// Get the current parsing token.
		token = jp.getCurrentToken();
		
		// If we are at the end or have an empty array, we are done.
		if (token == JsonToken.END_ARRAY) {
			isLast = true;
		} else {
		
			// Now process the record.
			if (token != JsonToken.START_OBJECT)
				throw new JsonParseException("Expected START_OBJECT for facets element", null);
				
			// Read in query object.
			currentRecord = jp.readValueAs(FacetRecord.class);

			recordCount++;
			
			// Move to next token to prepare for follow up call.
			token = jp.nextToken();
			if (token == JsonToken.END_ARRAY) {
				isLast = true;
				parseContext = ParseLevel.END_FACETS;
			}
		}
	
		return currentRecord;
	}
	
	public boolean isLast() {
		return isLast;
	}

}
